home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / libs / knowhow4 / slang.cpp < prev    next >
C/C++ Source or Header  |  1994-10-30  |  21KB  |  811 lines

  1. #include "slang.h"
  2. #include <stdio.h>
  3. #include <dos.h>
  4.  
  5. #include <io.h>
  6. #include <FCNTL.H>
  7.  
  8. ////////////////////////
  9. Slang::Slang()
  10.     {
  11.     error = 0;                     // Effor flag - not error number
  12.     tok = 0;                       // Token type
  13.     theName = NULL;                // Used with arrays to keep name and index
  14.     variables = new VarTable();    // Table of veriables
  15.     for_used = 0;                  // FOR stack initialization
  16.     sub_used = 0;                  // -//- gosub
  17.     play_used = 0;                 // -//- external program files
  18.     program = NULL;                // Current program.
  19.     labels = new label[NUM_LAB];   // Labels initialization
  20.     }
  21. ///////////////////////////
  22. Slang::~Slang()
  23.     {
  24.     for(int i = 1; i <= play_used; i++)   // Remove all unnecessary file
  25.     delete playstack[i];              // names from play stack.
  26.     delete labels;
  27.     delete variables;
  28.     delete program;
  29.     delete theName;
  30.     }
  31. ///////////////////////////
  32. void Slang::basic(char* p_buf)            // p_buf contain program to run
  33.     {
  34.     prog = program = p_buf;               // Set program and tracer.
  35.     scan_labels();                        // Remove old labels and search new
  36.     if(error)                             // Check for labels error
  37.     return;
  38.     do
  39.     interprete();                     // Run program operand by operand
  40.     while(tok != FINISHED && tok != END && !error);
  41.     }
  42. ///////////////////////////////////////////////////////////////////////////
  43. void Slang::terminate()
  44.     {
  45.     }
  46. ///////////////////////////////////////////////////////////////////////////
  47. void  Slang::interprete()
  48.     {
  49.     int oldtok;
  50.     kh_error_code = KH_SUCCESS;
  51.     do {
  52.     terminate();               // User-defined STOP-event
  53.     if(error)                  // Error detected
  54.         {
  55.         if(sub_used > 0)
  56.         {
  57.         prog = sub_pop();
  58.         return;
  59.         }
  60.         while(play_used > 1)   // We need clear all nested programs and
  61.         delete playpop();  // "program" itself.
  62.         delete program;
  63.         program = NULL;
  64.         delete variables;            // We also clears all variables
  65.         variables = new VarTable();  // and initialize them again.
  66.         return;
  67.         }
  68.     token_type = get_token();     // Get next lexem
  69.     if(token_type == VARIABLE)    // If it is name (only x = ... or
  70.         {                         // a[12]... recognized
  71.         putback();                // Put it back to input stream and
  72.         assigment();              // make assignment.
  73.         }
  74.     else
  75.         switch(oldtok = tok)  // If it is operator or subroutine call
  76.         {
  77.         case GOTO:     slang_goto(); break;   // This block is the
  78.         case LABEL:    find_eol(); break;     // same in Slang and in
  79.         case GOSUB:    gosub();    break;     // childs. It realize
  80.         case PLAYEX:     play();     break;   // language facilities.
  81.         case PRINT:    print();    break;
  82.         case IF:       slang_if();  break;
  83.         case FOR:      slang_for(); break;
  84.         case NEXT:     next();     break;
  85.         case INPUT:    input();    break;
  86.         case RETURN:   sub_return();  break;
  87.         case DELETE:   del(); break;
  88.         case PAUSE:    pause(); break;
  89.  
  90.         case END:                 // End of "main" or played program.
  91.             if(play_used == 1)    // If it is main program, then
  92.             return;           // no action is taken.
  93.  
  94.             delete playpop();     // If we play external file, pop
  95.                       // it from program stack, and
  96.             delete program;
  97.             play_stack* p_s;      // Then we load previous file
  98.             program = load_program((p_s = playpop())->prog);
  99.             prog = program + p_s->shift;
  100.             delete p_s;
  101.             scan_labels();        // And scan it for labels
  102.             break;
  103.         }
  104.     } while((oldtok != FINISHED ) && (oldtok != RETURN));
  105.     }
  106. //////////////////////
  107. void Slang::del()   // for((str)a ? ... not supported
  108.     {
  109.     while(tok != EOL && tok != FINISHED && !error)
  110.     {
  111.     get_token();  // obtain variable name
  112.     if(!isalpha(*token))
  113.         { serror(4); return; }
  114.     delete variables->remove(token);
  115.     get_token();
  116.     if(tok != EOL && token[0] != ',')
  117.         { serror(0); return; }
  118.     }
  119.     }
  120. //////////////////////
  121. void Slang::assigment()               // assignment or array initialization
  122.     {
  123.     if(error)                         // If error occured before call
  124.     return;
  125.     double value, index;              // Value of REAL or index of ARRAY
  126.     char name[80], *str_value;        // Name of variable and STRING value
  127.  
  128.     get_token();                      // Obtain variable name
  129.     if(!isalpha(*token))              // If it is not variable name
  130.     {   serror(4);     return;  }
  131.  
  132.     strcpy(name, token);                  // Copy name to storage place
  133.     get_token();                          // '=' or [
  134.     if(*token != '=' && *token != '[')    // Only x = ... and a[12]; are
  135.     {   serror(18);  return;  }       // legal
  136.     if(*token == '[')                 // Array
  137.     {
  138.     get_exp(&index);              // Array index could be expression too
  139.     get_token();                  // '=' or ';'
  140.         if(*token != '=' && *token != ';') // = in assig. or ; in decl.
  141.         {   serror(18);  return;  }
  142.  
  143.         if(*token == ';')    // ';' initializes array of 'index' elements
  144.             {
  145.         if(!variables->assign((int)index, name)) // Name is used by !ARRAY
  146.             serror(20);
  147.             return;
  148.         }
  149.     if(error || (get_exp(&value) != NULL))     // Value to assign
  150.         {
  151.         serror(2);
  152.         return;
  153.         }
  154.         variables->assign((double)value, name, index);
  155.         return;
  156.     }
  157.  
  158.     get_token();                     // '"...' or value of var
  159.     if(token_type == QUOTE)          // it is string
  160.     variables->assign((char*)token, name);
  161.     else                             // it is a = (real)b or a = (str)b
  162.     {
  163.     putback();
  164.     str_value = get_exp(&value);
  165.     switch(variable_type)
  166.         {
  167.         case REAL:    variables->assign((double)value, name);     break;
  168.         case STR :  variables->assign((char*)str_value, name); break;
  169.         }
  170.     }
  171.     }
  172. //////////////////////
  173. void Slang::math(double* result)
  174.     {
  175.     if(error)
  176.         return;
  177.  
  178.     double x;
  179.     int t = tok;
  180.     get_token();    // "("
  181.     if(*token != '(')
  182.         {
  183.     serror(1);
  184.         return;
  185.         }
  186.     get_token();   // sin argument
  187.     if(token_type != VARIABLE && token_type != NUMBER)
  188.         {
  189.     serror(2);
  190.         return;
  191.         }
  192.     putback();
  193.     get_exp(&x);      // if sin(2*x+1)
  194.     switch(t)
  195.         {
  196.         case SIN: *result = sin(M_PI * 2 * x / 360); break;
  197.         case COS: *result = cos(M_PI * 2 * x / 360); break;
  198.         case TAN: *result = tan(M_PI * 2 * x / 360); break;
  199.         case ASIN:
  200.         if(x > 1 || x < -1)
  201.             {
  202.         serror(16);
  203.                 return;
  204.                 }
  205.         *result = 180 * asin(x) / M_PI;
  206.         break;
  207.         case ACOS:
  208.         if(x > 1 || x < -1)
  209.             {
  210.         serror(16);
  211.                 return;
  212.                 }
  213.         *result = 180 * acos(x) / M_PI;
  214.         break;
  215.         case ATAN:
  216.             *result = 180 * atan(x) / M_PI; break;
  217.         case ABS: *result = abs(x); break;
  218.         case EXP: *result = exp(x); break;
  219.         case LOG: *result = log(x); break;
  220.         case LG:  *result = log10(x); break;
  221.         default: serror(0);
  222.         }
  223.     }
  224. //////////////////////
  225. void Slang::pause()
  226.     {
  227.     if(error)
  228.         return;
  229.  
  230. #ifdef DOS_BGI
  231.     double value;
  232.     get_token();
  233.     get_token();
  234.  
  235.     if(token_type == NUMBER || token_type == VARIABLE)
  236.         {
  237.         putback();
  238.     get_exp(&value);
  239.         delay(value);
  240.         }
  241.     else
  242.     serror(0);
  243. #endif DOS_BGI
  244.     }
  245. //////////////////////
  246. void Slang::print()
  247.     {
  248.     if(error)
  249.         return;
  250.  
  251.     double value; char* str_value;
  252.     int len = 0;
  253.     do {
  254.     get_token();
  255.     if(tok == EOL || tok == FINISHED /* || tok == REMARK */ || error)
  256.         break;
  257.     switch(token_type)
  258.         {
  259.         case QUOTE:       // it's string
  260.         printf(token);
  261.         len += strlen(token);
  262.         get_token();
  263.         break;
  264.         default:          // it's expression
  265.         putback();
  266.         str_value = get_exp(&value);
  267.         switch(variable_type)
  268.             {
  269.             case REAL:
  270.             case ARRAY: len += printf("%f", value); break;
  271.             case STR :  len += printf(str_value);   break;
  272.             }
  273.         }
  274.     switch(*token)
  275.         {
  276.         case ';':  printf("\n"); break;
  277.         case ',':  break;               // nonthing to do
  278.         default :
  279.         if(tok != EOL && tok != FINISHED)
  280.             {
  281.             serror(0);
  282.                     return;
  283.                     }
  284.         }
  285.     } while(*token == ';' || *token == ',');
  286.     }
  287. ////////////////////
  288. void Slang::get_label()              // Check label for errors and fill
  289.     {                                // the table of labels.
  290.     if(error)                                // If previus functions set
  291.         return;                              // error flag - return
  292.  
  293.     int addr;                        // Number in the table
  294.     get_token();                     // Read label name
  295.     addr = get_next_label(token);    // -1 (overflov), -2 (duplicated labels)
  296.     if(addr == -1)                   // or number of labels in table (index
  297.         {                            // for new label in table.
  298.     serror(5);
  299.         return;
  300.         }
  301.     if(addr == -2)
  302.     {
  303.     serror(6);
  304.         return;
  305.         }
  306.     strcpy(labels[addr].name, token);
  307.     labels[addr].p = prog;
  308.     }
  309. ////////////////////
  310. void Slang::scan_labels()     // Scan program for labels
  311.     {
  312.     int addr;   char* temp;
  313.     label_init();             // Set all label names to zero
  314.     temp = prog;
  315.     do{                       // In cycle, read token, if it is label,
  316.     get_token();          // register it in get_label, else go to the
  317.         if(error)             // next line of program. This job should be
  318.             return;           // done only fr "main" code. Result is labels
  319.         if(tok == LABEL)      // in "main" function, and we now are at the
  320.             {                 // first subroutine.
  321.         get_label();
  322.             find_eol();
  323.             }
  324.     } while(tok != END && tok != FINISHED);
  325.     char* temp1 = prog;
  326.     do {                                  // Scan rest of code for labels
  327.     get_token();                      // and subroutines.
  328.     if(tok == GOSUB)
  329.             {
  330.         get_label();
  331.             find_return();
  332.             find_eol();
  333.             }
  334.     } while(tok != FINISHED);
  335.     prog = temp1;
  336.     do {                                  // Scan rest of code for labels
  337.     get_token();                      // and subroutines.
  338.     if(tok == LABEL)
  339.             {
  340.         get_label();
  341.             find_eol();
  342.             }
  343.     } while(tok != FINISHED);
  344.  
  345.     prog = temp;
  346.     }
  347. ///////////////////////////
  348. void Slang::find_eol()
  349.     {
  350.     while(*prog != '\n' && *prog != '\0') ++prog;
  351.     if(*prog) prog++;
  352.     }
  353. //////////////////////////
  354. void Slang::find_return()
  355.     {
  356.     while(tok != RETURN)
  357.     get_token();
  358.     find_eol();
  359.     }
  360. //////////////////////////
  361. int Slang::get_next_label(char* s)
  362.     {
  363.     int t;
  364.     for(t = 0; t < NUM_LAB; ++t)
  365.     {
  366.     if(labels[t].name[0] == 0)
  367.         return t;
  368.     if(!strcmp(labels[t].name, s))
  369.         return -2; // duplicated labels
  370.     }
  371.     return -1;
  372.     }
  373. /////////////////////
  374. char* Slang::find_label(char* s)
  375.     {
  376.     int t;
  377.     for(t = 0; labels[t].name[0] != '\0' && t < NUM_LAB; ++t)
  378.     if(!strcmp(labels[t].name, s))
  379.         return labels[t].p;
  380.     return '\0';
  381.     }
  382. //////////////////////
  383. void Slang::label_init()
  384.     {
  385.     int t;
  386.     for(t = 0; t < NUM_LAB; ++t)
  387.     labels[t].name[0] = '\0';
  388.     }
  389. ////////////////////
  390. void Slang::slang_if()     // if((str)a ? (str)b) not supported
  391.     {              // and if(f(x)) not supported and if(a AND (b OR c)) too
  392.     if(error)
  393.         return;
  394.  
  395.     double x, y;    int cond;    char op, op1;
  396.     get_exp(&x);   // left expression
  397.     if(!strchr("=<>", *token))
  398.     {  serror(0); return;    }
  399.     op = *token; op1 = *(token + 1);
  400.     get_exp(&y); // right expression
  401.     cond = 0;
  402.     switch(op)  // =, >=, <=, =>, =<, <>,><
  403.     {
  404.     case '=':
  405.         switch(op1)
  406.         {
  407.         case 0:
  408.             if(x == y) cond = 1;
  409.             break;
  410.         case '>':
  411.             if(x >= y) cond = 1;
  412.             break;
  413.         case '<':
  414.             if(x <= y) cond = 1;
  415.             break;
  416.         }
  417.         break;
  418.     case '<':
  419.         switch(op1)
  420.         {
  421.         case 0:
  422.             if(x < y) cond = 1;
  423.             break;
  424.         case '=':
  425.             if(x <= y) cond = 1;
  426.             break;
  427.         case '>':
  428.             if(x != y) cond = 1;
  429.             break;
  430.         }
  431.         break;
  432.     case '>':
  433.         switch(op1)
  434.         {
  435.         case 0:
  436.             if(x > y) cond = 1;
  437.             break;
  438.         case '=':
  439.             if(x >= y) cond = 1;
  440.             break;
  441.         case '<':
  442.             if(x != y) cond = 1;
  443.             break;
  444.         }
  445.         break;
  446.     default: serror(0); return;
  447.     }
  448.     if(cond)
  449.     {
  450.     if(tok != THEN)
  451.         {
  452.         serror(8);   return;
  453.         }
  454.     }
  455.     else find_eol();
  456.     }
  457. //////////////////////
  458. void Slang::slang_for()   // for((str)a ? ... not supported
  459.     {
  460.     if(error)
  461.         return;
  462.     struct for_stack i;
  463.     double value;
  464.     get_token();  // obtain cycle variable
  465.     if(!isalpha(*token))
  466.     { serror(4); return;    }
  467.     strcpy(i.name, token);
  468.     get_token();  // '='
  469.     if(*token != '=')
  470.     {  serror(3); return;    }
  471.     get_exp(&value);  // from
  472.  
  473.     variables->assign(value, i.name); //variableName);
  474.     Variable* def = variables->find(i.name);
  475.  
  476.     if(tok != TO)
  477.     { serror(9); return; }
  478.     get_exp(&i.endval);
  479.     if(value >= def->d)
  480.     {
  481.     i.entrance = prog;
  482.     for_push(i);
  483.     }
  484.     else
  485.     while(tok != NEXT)
  486.         get_token();
  487.     }
  488. ///////////////////////////
  489. void Slang::next()
  490.     {
  491.     if(error)
  492.         return;
  493.  
  494.     struct for_stack i;
  495.     i = for_pop();
  496.  
  497.     Variable* variableName = variables->find(i.name);
  498.     variableName->d++;
  499.  
  500.     if(variableName->d > i.endval) return;
  501.     for_push(i);
  502.     prog = i.entrance;
  503.     }
  504. //////////////////////////
  505. void Slang::for_push(struct for_stack i)
  506.     {
  507.     if(error)
  508.         return;
  509.  
  510.     if(for_used > FOR_NEST)
  511.     { serror(10); return; }
  512.     fstack[for_used] = i;
  513.     for_used++;
  514.     }
  515. ///////////////////////
  516. for_stack Slang::for_pop()
  517.     {
  518.     for_used--;
  519.     if(for_used < 0)
  520.     serror(11); 
  521.     return(fstack[for_used]);
  522.     }
  523. ///////////////////////
  524. void Slang::input()
  525.     {
  526.     if(error)
  527.         return;
  528.  
  529.     double i; char str[80]; // input string
  530.     get_token();
  531.     if(token_type == QUOTE)
  532.     {
  533.     printf(token);
  534.     get_token();
  535.     if(*token != ',')
  536.         { serror(0); return; }
  537.     get_token();
  538.     }
  539.     else
  540.     printf("? ");
  541.     Variable* v = variables->find(token);
  542.     switch(v->type)
  543.     {
  544.     case STR:     // if exist (str)variable - assign str, else - real
  545.         gets(str);
  546.         variables->assign(str, token);
  547.         break;
  548.     case REAL:
  549.         char t_token[80];
  550.         strcpy(t_token, token);
  551.         gets(str);
  552.         char* temp = prog;
  553.         prog = str;
  554.         get_exp(&i);
  555.         prog = temp;
  556.         variables->assign(i, t_token);
  557.             break;
  558.         case ARRAY:
  559.         strcpy(t_token, token);   // t_token keep name
  560.  
  561.             double value;
  562.             get_token();
  563.         get_exp(&i);              // i keeps index
  564.  
  565.         gets(str);
  566.         temp = prog;
  567.         prog = str;
  568.         get_exp(&value);          // value keeps input
  569.         prog = temp;
  570.         variables->assign(value, t_token, (int)i);
  571.             break;
  572.     }
  573.     }
  574. ////////////////////////
  575. void Slang::slang_goto()
  576.     {
  577.     if(error)
  578.         return;
  579.  
  580.     char* loc;
  581.     get_token();         // name
  582.     loc = find_label(token);
  583.     if(loc == '\0')
  584.     { serror(7); return; }
  585.     prog = loc;
  586.     }
  587. ////////////////////////
  588. void Slang::gosub()
  589.     {
  590.     if(error)
  591.         return;
  592.  
  593.     char* loc;
  594.     get_token();         // name
  595.     loc = find_label(token);
  596.     if(loc == '\0')
  597.     { serror(7); return; }
  598.     else
  599.     {
  600.     int arg1 = assign_arguments();
  601.     sub_push(prog);
  602.     prog = loc;
  603.     int arg2 = reassign_arguments();
  604.     if(arg1 != arg2)
  605.         { serror(15); return; }
  606.     interprete();
  607.     }
  608.     }
  609. //////////////////////
  610. void Slang::play()          // Pass the control to the external file
  611.     {
  612.     if(error)
  613.         return;
  614.     get_token();    // "("
  615.     if(*token != '(')
  616.         {
  617.     serror(1);
  618.         return;
  619.         }
  620.  
  621.     get_token();                      // Name of file. !!! No error check !!!
  622.     uint sh = prog - program;
  623.     delete program;                        // Delete current program
  624.     prog = program = load_program(token);  // And replace it with new
  625.     if(play_used > 1)
  626.         playstack[play_used - 1]->shift = sh;   //prog - program;
  627.  
  628.     scan_labels();                         // Set new labels
  629.     }
  630. //////////////////////
  631. void Slang::sub_return()                // Return from subroutine
  632.     {
  633.     if(error)
  634.         return;
  635.  
  636.     double value; char* str_value;
  637.     get_token();                        // If RETURN a
  638.     if(token_type == DELIMITER)         // EOL
  639.     putback();
  640.     else                                // If RETURN with parameters
  641.     {
  642.     putback();
  643.     str_value = get_exp(&value);
  644.     switch(variable_type)
  645.         {
  646.         case REAL:    variables->assign(value, "retval");  break;
  647.         case STR:   variables->assign(str_value, "retval"); break;
  648.             default: serror(0); break;
  649.         }
  650.     }
  651.     prog = sub_pop();
  652.     }
  653. /////////////////////
  654. void Slang::sub_push(char* s)
  655.     {
  656.     if(error)
  657.         return;
  658.  
  659.     sub_used++;
  660.     if(sub_used == SUB_NEST)
  661.     { serror(12); return; }
  662.     substack[sub_used] = s;
  663.     }
  664. ////////////////////
  665. char* Slang::sub_pop()
  666.     {
  667.     if(sub_used == 0)
  668.     serror(13);
  669.     return(substack[sub_used--]);
  670.     }
  671. /////////////////////////
  672. void Slang::playpush(char* s, int shift)
  673.     {
  674.     if(error)
  675.         return;
  676.  
  677.     play_used++;
  678.     if(play_used == SUB_NEST)
  679.     {    serror(12);    return;    }
  680.     play_stack* p = new play_stack(s, shift);
  681.     playstack[play_used] = p;
  682.     }
  683. ////////////////////
  684. play_stack* Slang::playpop()
  685.     {
  686.     if(play_used == 0)
  687.     serror(13);
  688.     return (playstack[play_used--]);
  689.     }
  690. /////////////////////////
  691. int Slang::assign_arguments()
  692.     {
  693.     if(error)
  694.         return 0;
  695.  
  696.     double value;  char* str_value; int i = 0;   char num[10]; char name[10];
  697.     get_token();  get_token();        // '(' and  ')'  ?
  698.     while(*token != ')')
  699.     {
  700.     strcpy(name, itoa(i, num, 10));   // <= 20 arguments
  701.     switch(token_type)
  702.         {
  703.         case QUOTE:
  704.         variables->assign((char*)token, name);
  705.         get_token();              // ',' or ')'
  706.         i++;
  707.         break;
  708.         case NUMBER:
  709.         case VARIABLE:
  710.         putback();
  711.         str_value = get_exp(&value);
  712.         switch(variable_type)
  713.             {
  714.                     case ARRAY:
  715.             case REAL:  variables->assign(value, name); break;
  716.             case STR:   variables->assign((char*)str_value, name); break;
  717.             }
  718.         i++;
  719.         break;
  720.         default: get_token();
  721.         }
  722.     }
  723.     return i;
  724.     }
  725. ///////////////////////
  726. int Slang::reassign_arguments()
  727.     {
  728.     if(error)
  729.         return 0;
  730.  
  731.     char str_value[80];   int i = 0;    char num[10];
  732.     get_token();  // '('
  733.     get_token();  // ')' ?
  734.     while(*token != ')')
  735.     {
  736.     char name[10];
  737.     strcpy(name, itoa(i, num, 10));   // <= 10 arguments
  738.  
  739.     Variable* inName = variables->find(name);
  740.     if(inName->type == REAL)
  741.             variables->assign(inName->d, token);
  742.     else
  743.             variables->assign(inName->s, token);
  744.  
  745.     i++; get_token();          //   ',' or ')'
  746.     if(*token == ',')
  747.         get_token();
  748.     }
  749.     return i;
  750.     }
  751. ///////////////////////
  752. char* Slang::load_program(char* filename)
  753.     {
  754.     if(error)
  755.         return NULL;
  756.  
  757.     int f;
  758.     if((f = open(filename, O_RDONLY | O_BINARY)) == -1)
  759.         { serror(17); return NULL; }
  760.  
  761.     long fl = filelength(f);
  762.     if (fl >= PROG_SIZE)
  763.     {
  764.     serror(21);
  765.         close(f);
  766.     return NULL;
  767.     }
  768.     char* p_buf = new char[fl + 3];
  769.     int n = read(f, p_buf, fl);
  770.     if(n < 0)
  771.     {
  772.     close(f);
  773.     delete p_buf;
  774.         p_buf = NULL;
  775.     return NULL;
  776.     }
  777.     close(f);
  778.  
  779.     p_buf[fl] = '\r'; p_buf[fl + 1] = '\n'; p_buf[fl + 2] = '\0';
  780.     playpush(filename, 0);
  781.     return p_buf;
  782.     }
  783.  
  784. ////////////////////////////////// DOS Demo /////////////////////////////////
  785. /*
  786. #include <conio.h>     // only for interruption on key pressed **************
  787. class Demo : public Slang
  788.     {
  789.     virtual void terminate();  // User-defined terminator (ESC and so on)
  790.     };
  791. /////////////
  792. void Demo::terminate()
  793.     {
  794.     if(kbhit())
  795.     {
  796.     getch();
  797.     if(kbhit())
  798.         getch();
  799.     serror(23);
  800.     }
  801.     }
  802. ///////////////////////////////////////////////////////////////////////////
  803. void main()
  804.     {
  805.     Demo* basic = new Demo();
  806.     basic->basic(basic->load_program("work.bas"));
  807.     delete basic;
  808.     printf("%s", "\n");
  809.     }
  810. //////////////////////////////// End of DOS Demo ////////////////////////////
  811. */